package com.symaster.gameengine.e2d.renderer;

import com.symaster.gameengine.core.Renderer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.stb.STBImage;
import org.lwjgl.system.MemoryStack;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

/**
 * 图片渲染器
 *
 * @author yinmiao
 * @version 2023/11/16
 */
public class ImageRenderer extends Renderer {

    private int width;
    private int height;
    private int imgTexture = 0;

    private ByteBuffer resourceBuffer;
    private String fileName;

    public int getImgTexture() {
        return imgTexture;
    }

    public ImageRenderer() {
    }

    public ImageRenderer(String fileName) {
        this.fileName = fileName;
    }

    public ImageRenderer(ByteBuffer resourceBuffer) {
        this.resourceBuffer = resourceBuffer;
    }

    @Override
    public int getHeight() {
        return this.height;
    }

    @Override
    public int getWidth() {
        return this.width;
    }

    /**
     * 子组件使用, 在当前Fbo缓冲区里面绘制
     */
    @Override
    protected void draw() {
        // 启用2D纹理绘制
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        // 绑定到当前图片纹理
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, imgTexture);
        // 绘制纹理
        this.fboRenderScene(true);
        // 禁用2D纹理绘制
        GL11.glDisable(GL11.GL_TEXTURE_2D);
    }

    @Override
    public void resourceLoad() {
        if (this.imgTexture != 0) {
            return;
        }

        try (MemoryStack memoryStack = MemoryStack.stackPush()) {
            IntBuffer widthCallback = memoryStack.mallocInt(1);
            IntBuffer heightCallback = memoryStack.mallocInt(1);
            IntBuffer channelsCallback = memoryStack.mallocInt(1);

            ByteBuffer image;

            if (resourceBuffer != null) {
                image = STBImage.stbi_load_from_memory(resourceBuffer, widthCallback, heightCallback, channelsCallback, 4);
            } else {
                image = STBImage.stbi_load(fileName, widthCallback, heightCallback, channelsCallback, 4);
            }

            if (image == null) {
                throw new RuntimeException("Failed to load image: " + STBImage.stbi_failure_reason());
            }

            this.width = widthCallback.get();
            this.height = heightCallback.get();

            // 创建纹理ID
            this.imgTexture = GL11.glGenTextures();
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, imgTexture);

            // 设置纹理参数
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);

            // 将图片数据上传到 GPU
            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, this.width, this.height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, image);

            // 生成 mipmap
            GL30.glGenerateMipmap(GL30.GL_TEXTURE_2D);

            // 释放内存
            STBImage.stbi_image_free(image);
        }
    }
}
